package cn.king.springframework.beans.factory.support;

import cn.hutool.core.bean.BeanUtil;
import cn.king.springframework.beans.BeanException;
import cn.king.springframework.beans.factory.config.BeanDefinition;

import java.lang.reflect.Constructor;
import java.util.List;

/**
 * @Description:TODO
 * @Author:wangkun
 * @ClassName:AbstractAutowireCapableBeanFactory
 * @Package:cn.king.springframework.beans.factory.support
 * @Date:2022年04月09日 22:12
 * @Version:1.0
 * @Project:simple-spring
 */
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
    private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition,Object[] args) {
        Object bean = null;
        try {
            //jdk9后建议使用的方式
            // beanDefinition.getBeanClass().getDeclaredConstructor().newInstance();
            bean = createBeanInstance(beanName,beanDefinition,args);
        } catch (Exception e) {
            throw  new BeanException("Instantiation of bean failed", e);
        }
        addSingleton(beanName,bean);
        return bean;
    }

    protected  Object createBeanInstance(String beanName, BeanDefinition beanDefinition,Object[] args){
        Constructor constructor = null;
        Class<?> beanClass = beanDefinition.getBeanClass();
        Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
        //查找匹配的构造函数
        for(Constructor c:declaredConstructors){
            if(null != args && c.getParameterTypes().length == args.length){
                constructor = c;
                break;
            }
        }
        return getInstantiationStrategy().instantiate(beanDefinition,beanName,constructor,args);
    }

    public InstantiationStrategy getInstantiationStrategy() {
        return instantiationStrategy;
    }

    public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
        this.instantiationStrategy = instantiationStrategy;
    }


}
